﻿var DriverPage: FrontController.BasePage;
window.onload = () => {
    DriverPage = new FrontController.BasePage();
    DriverPage.LoadSubPage("Login");
};
enum __FormMethod { GET, POST };
module FrontController {
    export class Helper {
        constructor() { }
        static GetXmlResponseFromServer(Url: string, method: __FormMethod, async: boolean): XMLDocument {
            return <XMLDocument>(this.callServer(Url, method, async).responseXML);
        }
        static GetHtmlResponseFromServer(Url: string, method: __FormMethod, async: boolean): string {
            return this.callServer(Url, method, async).responseText;
        }
        private static callServer(Url: string, method: __FormMethod, async: boolean): XMLHttpRequest {
            var objHttpReq = new XMLHttpRequest();
            objHttpReq.open(method == __FormMethod.GET ? "get" : "post", Url, async);
            objHttpReq.send();
            if (objHttpReq.readyState == 4 && objHttpReq.status == 200)
                return objHttpReq;
        }
        static CreateInstance<T>(ClassFullName: string): T {
            var reference: T;
            var className: string[] = ClassFullName.split('.');
            switch (className.length) {
                case 1:
                    reference = Object.create(window[className[0]].prototype);
                    break;
                case 2:
                    reference = Object.create(window[className[0]][className[1]].prototype);
                    reference.constructor.apply(reference);
                    break;
            }
            return <T>reference;
        }
        static BindTemplate(data:any[], template: string): string {
            var el: HTMLElement = document.createElement("div");
            el.innerHTML = template;
            var itemTemplate: HTMLElement = <HTMLElement>el.getElementsByTagName("ItemTemplate").item(0);
            var itemTemplateText: string = itemTemplate.innerHTML;
            var itemTemplateOuterText: string = itemTemplate.outerHTML;
            var resultItemTemplate: string = "";
            var regex = new RegExp("Bind\\((.*?)\\)", "g");
            var bindValues: string[] = itemTemplateText.match(regex);
            for (var i: number = 0; i < data.length; i++) {
                var replacedItemTemplate: string = itemTemplateText;
                for (var j: number = 0; j < bindValues.length; j++) {
                    var dataProp: string = bindValues[j].match(new RegExp("Bind\\((.*?)\\)"))[1];
                    replacedItemTemplate = replacedItemTemplate.replace(regex, <string>data[i][dataProp]);
                }                
                resultItemTemplate += replacedItemTemplate;
            }
            return el.innerHTML.replace(itemTemplate.outerHTML, resultItemTemplate);
        }
    }
    export class UserControl {
        spanElement: HTMLSpanElement; Controls: UserControl[];
        constructor() {
            this.spanElement = document.createElement("span");
            this.Controls = [];
        }
        LoadSpanElement(url: string, id: string) {
            this.spanElement.id = id;
            this.spanElement.innerHTML = Helper.GetHtmlResponseFromServer(url, __FormMethod.GET, false);
        }
        SetEvents() { }
        LoadUserControls(el: HTMLElement) {
            var userControls: NodeListOf<HTMLObjectElement> = el.getElementsByTagName("object");
            for (var i: number = 0; i < userControls.length; i++) {
                var x: HTMLObjectElement = userControls[i];
                var userControl: UserControl = Helper.CreateInstance<UserControl>(x.attributes.getNamedItem("classid").value);
                userControl.LoadSpanElement(x.attributes.getNamedItem("data").value, x.attributes.getNamedItem("id").value);
                userControl.spanElement.id = x.id;
                x.parentNode.replaceChild(userControl.spanElement, x);
                userControl.SetEvents();
                this.Controls.push(userControl);
                this.LoadUserControls(x);
            }
        }
        FindChildElementById<T extends HTMLElement>(id: string): T {
            return <T>this.spanElement.querySelector('#' + id);
        }
    }
    export class BaseSubPage extends UserControl {
        SubPageName: string; Url: string; element: HTMLElement; Name: string;
        FindUserControlById<T extends UserControl>(id: string): T {
            for (var i: number = 0; i < this.Controls.length; i++) {
                if (this.Controls[i].spanElement.id == id)
                    return <T>this.Controls[i];
            }
            return null;
        }
        constructor() {
            super();
            this.element = document.getElementById("divSubpage");
            this.element.innerHTML = "";
            this.element.appendChild(this.spanElement);
        }
        LoadSubPage() {
            this.LoadSpanElement(this.Url, this.Name);
            this.LoadUserControls(this.element);
        }
    }
    export class BasePage {
        NavConfig: XMLDocument;
        divBreadcrumb: HTMLElement;
        pageHistory: any[];
        constructor() {
            this.NavConfig = Helper.GetXmlResponseFromServer("PageNavigation.xml", __FormMethod.GET, false);
            this.divBreadcrumb = document.getElementById("divBreadcrumb");
            this.pageHistory = [];
        }
        LoadSubPage(subpageName: string) {
            var subPageNode: Node;
            var nodes: NodeList = this.NavConfig.documentElement.getElementsByTagName("SubPage");
            for (var i: number = 0; i < nodes.length; i++) {
                if (nodes.item(i).attributes.getNamedItem("Name").value == subpageName) {
                    subPageNode = nodes.item(i);
                    break;
                }
            }
            var subpage: BaseSubPage = Helper.CreateInstance<BaseSubPage>(subPageNode.attributes.getNamedItem("CodeBehind").value);
            subpage.Name = subpageName;
            subpage.Url = subPageNode.attributes.getNamedItem("Url").value;
            var i: number;

            this.pageHistory.push({ SubPagename: subpageName });
            for (i = 0; i < this.pageHistory.length; i++) {
                if (this.pageHistory[i].SubPagename == subpageName)
                    break;
            }
            while (i + 1 < this.pageHistory.length) this.pageHistory.pop();
            var breadcrumbTemplate: string = Helper.GetHtmlResponseFromServer("Templates/Breadcrumb.html", __FormMethod.GET, false);
            this.divBreadcrumb.innerHTML = Helper.BindTemplate(this.pageHistory, breadcrumbTemplate);
            subpage.LoadSubPage();
            subpage.SetEvents();
        }
    }
}